package mylab.io.core.util;

import com.google.common.base.Strings;

import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

import cn.hutool.core.text.CharSequenceUtil;
import io.netty.bootstrap.AbstractBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import mylab.base.foundation.lang.Callback;


@Slf4j
@UtilityClass
public class NettyUtil {

    public ChannelFuture bind(AbstractBootstrap<?, ?> bootstrap, String host, int port) {
        ChannelFuture future;
        if (!Strings.isNullOrEmpty(host) && port >= 0) {
            future = bootstrap.bind(host, port);
        } else if (port >= 0) {
            future = bootstrap.bind(port);
        } else {
            future = bootstrap.bind(0);
        }

        return future;
    }

    public void closeChannel(Channel channel) {
        try {
            if (channel != null) {
                //清空channelHandler
                final ChannelPipeline pipeline = channel.pipeline();
                pipeline.names().stream().filter(name -> !CharSequenceUtil.containsIgnoreCase(name, "TailContext")).forEach(pipeline::remove);

                // 1. 停止接收新请求
                channel.config().setAutoRead(false);

                // 2. 发送关闭信号（如HTTP的connection:close）
                ChannelHandlerContext ctx = channel.pipeline().lastContext();
                ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);

                // 3. 等待处理中的请求完成
                EventLoopGroup group = channel.eventLoop().parent();
                group.shutdownGracefully(2, 15, TimeUnit.SECONDS);

                log.info("closeChannel completed");
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        } finally {
        }
    }

    public void dealFuture(ChannelFuture future, Callback<Void> callback) {
        dealFuture(future, callback, callback::onSuccess);
    }

    public void dealFuture(ChannelFuture future, Callback<Void> callback, Consumer<Void> successConsumer) {
        if (future == null || callback == null)
            return;

        future.addListener((ChannelFutureListener) f -> {
            //Uncompleted
            if (!f.isDone() && !f.isSuccess() && !f.isCancelled() && f.cause() == null) {
                callback.onFailure("I/O操作未完成");
            }

            //Completed by cancellation
            if (f.isDone() && f.isCancelled()) {
                callback.onFailure("I/O操作被取消");
            }

            //Completed with failure
            if (f.isDone() && f.cause() != null) {
                callback.onException(f.cause());
            }

            //Completed successfully
            if (f.isDone() && f.isSuccess()) {
                successConsumer.accept(null);
            }

        });
    }
}
